﻿namespace ZyGame.Event
{
    using System;
    using System.Collections.Generic;

    sealed class EventSystem : Singleton<EventSystem>
    {
        private List<IEventHandle> subscribers = new List<IEventHandle>();

        public EventSystem()
        {
            Subscribe<GameEventDispatcher>();
        }

        public void NotiflyEvent(string evtName, object args = null)
        {
            Client.Console.WriteLine("[NOTIFLY EVENT]" + evtName + " [EVENT DATA]:" + args?.ToString());
            for (int i = subscribers.Count - 1; i >= 0; i--)
            {
                subscribers[i].Notify(evtName, args);
            }
        }

        public T Subscribe<T>() where T : IEventHandle => (T)Subscribe(typeof(T));

        public void Unsubscribe<T>() where T : IEventHandle => Unsubscribe(typeof(T));

        public IEventHandle Subscribe(Type type)
        {
            Unsubscribe(type);
            IEventHandle subscriber = (IEventHandle)Activator.CreateInstance(type);
            subscribers.Add(subscriber);
            return subscriber;
        }

        public void Unsubscribe(Type type)
        {
            IEventHandle subscriber = subscribers.Find(x => x.GetType() == type);
            if (subscriber == null)
            {
                return;
            }

            subscribers.Remove(subscriber);
        }

        public void Register(string eventName, bool isOnce, Action<object> callback)
        {
            foreach (var item in subscribers)
            {
                item.Register(eventName, isOnce, callback);
            }
        }

        public void Unregister(string eventName, Action<object> callback)
        {
            foreach (var item in subscribers)
            {
                item.Unregister(eventName, callback);
            }
        }

        public void Clear(string evtName)
        {
            for (int i = 0; i < subscribers.Count; i++)
            {
                subscribers[i].Clear(evtName);
            }
        }

        public void Dispose()
        {
            this.subscribers.ForEach(x => x.Dispose());
            this.subscribers.Clear();
        }
    }
}